/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xos_cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../helper_objs/head.h"
#include "../data_struct/head.h"
#include "../config/head.h"
#include "../tools/head.h"
#include "../macro/head.h"
#include "../xos/head.h"
#include "../msg/head.h"
#include "state.h"
#include "hook.h"
#include "mgr.h"

namespace xos_cat
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static mgr * mgr_ptr = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    mgr::mgr()
    {
        mgr_ptr = this;
        m_pNotify = 0;
        m_pEvent = 0;
        m_pQueue = 0;
        m_pNum = 0;
    }

    mgr::~mgr()
    {
        mgr_ptr = 0;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // static functions

    xos_container::i_container * mgr::container()
    {
        return os::container();
    }

    mgr * mgr::get()
    {
        return mgr_ptr;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::notify( xos_box::i_msg *& p )
    {
        int ret = 0;

        m_pQueue->push_back( p );
        m_pEvent->set_event();
        m_pNum->add( 1 );
        p = 0;

        return ret;
    }

    int mgr::size()
    {
        int ret = 0;
        ret = m_pNum->get();
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    xos_box::i_notify * mgr::notify()
    {
        return m_pNotify;
    }

    int mgr::run()
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = init();
        }

        if( 0 == ret )
        {
            helper_main::get()->notify( MAIN_STARTING );
            loop();
        }

        {
            term();
        }

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::put_back_to_pool()
    {
        int ret = 0;
        return ret;
    }

    int mgr::init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = hook::init();
        }

        if( 0 == ret )
        {
            m_pEvent = mgr::container()->xos()->event();
        }

        if( 0 == ret )
        {
            m_pQueue = mgr::container()->box()->queue();
            m_pNum = mgr::container()->box()->lnum();
        }

        if( 0 == ret )
        {
            m_pNotify = helper_main::get()->clone();
            m_pNotify->set_msg_type( MSG_TYPE_NOTIFY );
            helper_net::init_notify();
        }

        if( 0 == ret )
        {
            xos_box::i_engine * pE = mgr::container()->box()->engine();
            pE->set_fast_num( config::get()->max_worker_thread_num );
            pE->set_slow_num( config::get()->max_slow_thread_num );
        }

        return ret;
    }

    int mgr::term()
    {
        int ret = 0;
        xos_stl::release_interface( m_pNotify );
        xos_stl::release_interface( m_pEvent );
        xos_stl::release_interface( m_pQueue );
        xos_stl::release_interface( m_pNum );
        hook::term();
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::loop()
    {
        while( !state::quitted() )
        {
            m_pEvent->wait( xos::i_event::EVENT_WAIT_INFINITE );
            while( 0 == proc() );
        }
        return 0;
    }

    int mgr::proc()
    {
        using namespace xos_box;
        int ret = 0;

        xos::f_runnable f_run = 0;
        i_msg * pMsg = 0;

        pMsg = (i_msg *)m_pQueue->pop_front();

        if( pMsg )
        {
            m_pNum->sub( 1 );
            f_run = pMsg->get_runnable( 0, 0 );
        }
        else
        {
            ret = 1;
        }

        if( f_run )
        {
            f_run( pMsg );
        }

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //

} // xos
